package com.quanyan.place.service.impl;

import com.quanyan.api.APIResponse;
import com.quanyan.common.Plugin.PageObj;
import com.quanyan.common.constants.Constants;
import com.quanyan.common.exception.BizException;
import com.quanyan.common.utils.BeanCopierUtils;
import com.quanyan.common.utils.Limit;
import com.quanyan.place.constants.PlaceConstants;
import com.quanyan.place.entity.*;
import com.quanyan.place.entity.apireq.ReqBannerAdmin;
import com.quanyan.place.entity.apireq.ReqBannerByCondition;
import com.quanyan.place.entity.apireq.ReqBannerPosition;
import com.quanyan.place.entity.apireq.ReqPlaceLeaderMsg;
import com.quanyan.place.entity.apiresp.RespBannerAdmin;
import com.quanyan.place.entity.apiresp.RespBannerPosition;
import com.quanyan.place.entity.apiresp.RespPlaceLeaderMsg;
import com.quanyan.place.mapper.*;
import com.quanyan.place.service.AppBannerService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by yue.yuan on 2017/5/24.
 */
@Service
public class AppBannerServiceImpl implements AppBannerService{
    @Autowired
    private TbAppBannerMapper tbAppBannerMapper;

    @Autowired
    private AppBannerMapper appBannerMapper;

    @Autowired
    private TbBannerCityMapper tbBannerCityMapper;

    @Autowired
    private TbBannerLayoutMapper tbBannerLayoutMapper;

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public APIResponse createBannerInfo(ReqBannerAdmin reqBannerAdmin) {
        validOnly(reqBannerAdmin.getPositionId());
        TbAppBanner tbAppBanner = convertReqToTb(reqBannerAdmin, 0);
        int count = tbAppBannerMapper.insertSelective(tbAppBanner);
        if(count <= 0) {
            return APIResponse.returnFail("create fail");
        }
        if(null != reqBannerAdmin.getCities()) {
            insertBannerCity(tbAppBanner.getId(), reqBannerAdmin.getCities());
        }
        return APIResponse.returnSuccess();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public APIResponse updateBannerInfo(ReqBannerAdmin reqBannerAdmin) {
        validOnly(reqBannerAdmin.getPositionId());
        TbAppBanner tbAppBanner = convertReqToTb(reqBannerAdmin, 1);
        if(null != tbAppBanner) {
            int count = tbAppBannerMapper.updateByPrimaryKeySelective(tbAppBanner);
            if(count <= 0) {
                return APIResponse.returnFail("update fail");
            }
        }
        if(null != reqBannerAdmin.getCities()) {
            deleteBannerCity(reqBannerAdmin.getId());
            insertBannerCity(reqBannerAdmin.getId(), reqBannerAdmin.getCities());
        }
        return APIResponse.returnSuccess();
    }

    @Override
    public APIResponse deleteBanner(Integer id) {
        TbAppBanner banner = tbAppBannerMapper.selectByPrimaryKey(id);
        if(banner.getIsDelete() == 1) {
            return APIResponse.returnFail("already delete");
        }
        TbAppBanner tbAppBanner = new TbAppBanner();
        tbAppBanner.setIsDelete(Constants.BYTE_ONE);
        tbAppBanner.setId(banner.getId());
        int count = tbAppBannerMapper.updateByPrimaryKeySelective(tbAppBanner);
        if(count <= 0) {
            return APIResponse.returnFail("update fail");
        }
        deleteBannerCity(banner.getId());
        return APIResponse.returnSuccess();
    }

    @Override
    public APIResponse listBannerInfo(ReqBannerByCondition condition) {
        return APIResponse.returnSuccess(listBanners(condition));
    }

    @Override
    public APIResponse<List<RespBannerPosition>> listBannerLayouts() {
        List<TbBannerLayout> bannerLayouts =
                tbBannerLayoutMapper.selectByExample(new TbBannerLayoutExample());
        ReqBannerByCondition condition = new ReqBannerByCondition();
        List<RespBannerPosition> resp = new ArrayList<RespBannerPosition>();
        for (TbBannerLayout bannerLayout : bannerLayouts) {
            //查询未结束的banner个数
            Integer count = appBannerMapper.countEffectiveBanner(bannerLayout.getId());
            RespBannerPosition position = new RespBannerPosition();
            BeanCopierUtils.copyProperties(bannerLayout, position);
            position.setBannerCount(count);
            //初始隐藏
            position.setShowImg(PlaceConstants.BANNER_POSITION_HIDE);
            //判断是否展示状态
            if(null != count && count > 0 && position.getIsDelete() == 0) {
                position.setShowImg(PlaceConstants.BANNER_POSITION_SHOW);
            }
            resp.add(position);
        }
        return APIResponse.returnSuccess(resp);
    }

    @Override
    public APIResponse queryLayout(Integer position) {
        TbBannerLayout bannerLayout =
                tbBannerLayoutMapper.selectByPrimaryKey(position);
        return APIResponse.returnSuccess(bannerLayout);
    }

    @Override
    public APIResponse updatePosition(ReqBannerPosition reqBannerPosition) {
        TbBannerLayout tbBannerLayout = new TbBannerLayout();
        tbBannerLayout.setId(reqBannerPosition.getPositionId());
        if(null != reqBannerPosition.getClose()) {
            tbBannerLayout.setIsDelete(reqBannerPosition.getClose().byteValue());
        }
        if(null != reqBannerPosition.getImgType()) {
            validChangeStyle(reqBannerPosition.getPositionId(), reqBannerPosition.getImgType());
            tbBannerLayout.setImgType(reqBannerPosition.getImgType());
        }
        int count = tbBannerLayoutMapper.
                updateByPrimaryKeySelective(tbBannerLayout);
        if(count <= 0) {
            return APIResponse.returnFail("update fail");
        }
        return APIResponse.returnSuccess();
    }

    private void validOnly(int positionId) {
        TbBannerLayout layout = tbBannerLayoutMapper.selectByPrimaryKey(positionId);
        if(layout.getImgType() != 4 && layout.getImgType() != 2) {
            return;
        }
        int count = appBannerMapper.countEffectiveBanner(positionId);
        if (count > 0) {
            throw new BizException("this position should take only one effective banner");
        }
    }

    private PageObj<List<RespBannerAdmin>> listBanners(ReqBannerByCondition condition) {
        List<RespBannerAdmin> list = new ArrayList<RespBannerAdmin>();

        int pageNum = condition.getPageNum() + 1;
        Limit limit = Limit.buildLimit(pageNum, condition.getPageSize());
        condition.setPageStart(limit.getStart());

        APIResponse<List<RespBannerPosition>> response = listBannerLayouts();
        List<RespBannerPosition> positions = response.getData();
        List<Integer> showPosition = new ArrayList<>();
        List<Integer> hidePosition = new ArrayList<>();
        for (RespBannerPosition position: positions) {
            if (position.getShowImg() == PlaceConstants.BANNER_POSITION_SHOW) {
                showPosition.add(position.getId());
            } else {
                hidePosition.add(position.getId());
            }
        }
        if(null != condition.getShowImg()) {
            //展示 广告位开启且包含有效广告,若没有，则直接返回，不再查询别的条件
            if (condition.getShowImg() == 1){
                if (CollectionUtils.isEmpty(showPosition)) {
                    return PageObj.create(0, condition.getPageNum(),
                            condition.getPageSize(), list);
                }
                condition.setPositionIds(showPosition);
            } else if (condition.getShowImg() == 0){
                if (CollectionUtils.isEmpty(hidePosition)) {
                    return PageObj.create(0, condition.getPageNum(),
                            condition.getPageSize(), list);
                }
                condition.setPositionIds(hidePosition);
            }
        }
        Integer total = appBannerMapper.countBannerByCondition(condition);
        if(null == total || total == 0) {
            return PageObj.create(total, condition.getPageNum(),
                    condition.getPageSize(), list);
        }
        Date curTime = new Date();
        list = appBannerMapper.queryBannerByCondition(condition);
        for (RespBannerAdmin banner : list ) {
            if(curTime.compareTo(banner.getStartTime()) < 0) {
                banner.setBannerStatus(1);
            } else if (curTime.compareTo(banner.getStartTime()) >= 0 &&
                    curTime.compareTo(banner.getEndTime()) <= 0) {
                banner.setBannerStatus(2);
            } else if (curTime.compareTo(banner.getEndTime()) > 0) {
                banner.setBannerStatus(3);
            }
            if (showPosition.contains(banner.getPositionId().intValue())) {
                banner.setShowImg(PlaceConstants.BANNER_POSITION_SHOW);
            } else {
                banner.setShowImg(PlaceConstants.BANNER_POSITION_HIDE);
            }
        }
        return PageObj.create(total, condition.getPageNum(),
                condition.getPageSize(), list);
    }

    private void validChangeStyle(int positionId, int imgType) {
        if (positionId == 1) {
            throw new BizException("can not update this banner position");
        }
        if (imgType == 4){
            throw new BizException("can not update this position img type to pop");
        }
        int count = appBannerMapper.countEffectiveBanner(positionId);
        if (count > 0) {
            throw new BizException("can not edit before none img");
        }
    }

    private TbAppBanner convertReqToTb(ReqBannerAdmin reqBannerAdmin,
                                       int operator) {
        TbAppBanner tbAppBanner = new TbAppBanner();
        boolean hasChange = false;
        if(operator == 1 && null != reqBannerAdmin.getId()) {
            tbAppBanner.setId(reqBannerAdmin.getId());
        }
        if(StringUtils.isNotBlank(reqBannerAdmin.getImgUrl())) {
            tbAppBanner.setImgUrl(reqBannerAdmin.getImgUrl());
            hasChange = true;
        }
        if(StringUtils.isNotBlank(reqBannerAdmin.getSportType())) {
            tbAppBanner.setSportType(reqBannerAdmin.getSportType());
            hasChange = true;
        }
        if(null != reqBannerAdmin.getPageType()) {
            tbAppBanner.setPageType(reqBannerAdmin.getPageType());
            hasChange = true;
        }
        if(StringUtils.isNotBlank(reqBannerAdmin.getPageUrl())) {
            tbAppBanner.setPageUrl(reqBannerAdmin.getPageUrl());
            hasChange = true;
        }
        if(StringUtils.isNotBlank(reqBannerAdmin.getAdminTitle())) {
            tbAppBanner.setAdminTitle(reqBannerAdmin.getAdminTitle());
            if (reqBannerAdmin.getImgType() != 2) {
                tbAppBanner.setTitle(reqBannerAdmin.getAdminTitle());
            }
            hasChange = true;
        }
        if(StringUtils.isNotBlank(reqBannerAdmin.getTitle())) {
            tbAppBanner.setTitle(reqBannerAdmin.getTitle());
            hasChange = true;
        }
        if(StringUtils.isNotBlank(reqBannerAdmin.getSubTitle())) {
            tbAppBanner.setSubTitle(reqBannerAdmin.getSubTitle());
            hasChange = true;
        }
        if(null != reqBannerAdmin.getStartTime()) {
            tbAppBanner.setStartTime(reqBannerAdmin.getStartTime());
            hasChange = true;
        }
        if(null != reqBannerAdmin.getEndTime()) {
            if(reqBannerAdmin.getEndTime().compareTo(reqBannerAdmin.getStartTime()) < 0) {
                throw new BizException("end time should later than start time");
            }
            tbAppBanner.setEndTime(reqBannerAdmin.getEndTime());
            hasChange = true;
        }
        if(null != reqBannerAdmin.getSeq()) {
            tbAppBanner.setSeq(reqBannerAdmin.getSeq());
            hasChange = true;
        }
        if(null != reqBannerAdmin.getPositionId()) {
            tbAppBanner.setPositionId(reqBannerAdmin.getPositionId());
            hasChange = true;
        }
        if(null != reqBannerAdmin.getPositionId()) {
            tbAppBanner.setPositionId(reqBannerAdmin.getPositionId());
            hasChange = true;
        }
        if(StringUtils.isNotBlank(reqBannerAdmin.getUserIds())) {
            tbAppBanner.setUids(reqBannerAdmin.getUserIds());
            hasChange = true;
        }
        return hasChange ? tbAppBanner : null;
    }

    private void insertBannerCity(int bannerId,
                                  List<Integer> cites) throws BizException {
        List<TbBannerCity> bannerCities = new ArrayList<TbBannerCity>();
        for (int i = 0; i < cites.size(); i++) {
            TbBannerCity bannerCity = new TbBannerCity();
            bannerCity.setBannerId(bannerId);
            bannerCity.setCityId(cites.get(i));
            bannerCities.add(bannerCity);
        }
        int count = appBannerMapper.batchInsertBannerCity(bannerCities);
        System.out.println(count);
        if(count <= 0) {
            throw new BizException("insert fail");
        }
    }

    private void deleteBannerCity(Integer bannerId) {
        TbBannerCityExample example = new TbBannerCityExample();
        example.createCriteria().andBannerIdEqualTo(bannerId);
        List<TbBannerCity> bannerCites = tbBannerCityMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(bannerCites)) {
            return;
        }
        int count = tbBannerCityMapper.deleteByExample(example);
        if(count <= 0) {
            throw new BizException("delete fail");
        }
    }

    @Autowired
    private TbBizPlaceLeaderMsgMapper placeLeaderMsgMapper;

    /**
     * 插入馆长信息
     * @param reqPlaceLeaderMsg
     * @return
     */
    @Override
    public APIResponse insertPlaceLeaderMsg(ReqPlaceLeaderMsg reqPlaceLeaderMsg) {
        EnumCheckLength checkLength = checkLeaderMsg(reqPlaceLeaderMsg);//检查字段长度
        if (!EnumCheckLength.CHECK_SUCC_LENGTH.equals(checkLength)) {
            return APIResponse.returnFail(checkLength.getValue());
        }
        TbBizPlaceLeaderMsg placeLeaderMsg =new TbBizPlaceLeaderMsg();
        placeLeaderMsg.setPlaceId(reqPlaceLeaderMsg.getPlaceId());
        placeLeaderMsg.setIconUrl(reqPlaceLeaderMsg.getUrl());
        placeLeaderMsg.setNickName(reqPlaceLeaderMsg.getNickName());
        placeLeaderMsg.setMotto(reqPlaceLeaderMsg.getMotto());
        placeLeaderMsg.setIntroduction(reqPlaceLeaderMsg.getIntroduce());
        placeLeaderMsg.setCreateTime(new Date());
        return placeLeaderMsgMapper.insertSelective(placeLeaderMsg) > 0 ? APIResponse.returnSuccess() : APIResponse.returnFail("录入失败");
    }

    /**
     * 编辑馆长信息
     * @param reqPlaceLeaderMsg
     * @return
     */
    @Override
    public APIResponse editPlaceLeaderMsg(ReqPlaceLeaderMsg reqPlaceLeaderMsg) {
        EnumCheckLength checkLength = checkLeaderMsg(reqPlaceLeaderMsg);//检查字段长度
        if (!EnumCheckLength.CHECK_SUCC_LENGTH.equals(checkLength)) {
            return APIResponse.returnFail(checkLength.getValue());
        }
        TbBizPlaceLeaderMsgExample placeLeaderMsgExample = new TbBizPlaceLeaderMsgExample();
        placeLeaderMsgExample.createCriteria().andPlaceIdEqualTo(reqPlaceLeaderMsg.getPlaceId());
        TbBizPlaceLeaderMsg placeLeaderMsg =new TbBizPlaceLeaderMsg();
        placeLeaderMsg.setPlaceId(reqPlaceLeaderMsg.getPlaceId());
        placeLeaderMsg.setIconUrl(reqPlaceLeaderMsg.getUrl());
        placeLeaderMsg.setNickName(reqPlaceLeaderMsg.getNickName());
        placeLeaderMsg.setMotto(reqPlaceLeaderMsg.getMotto());
        placeLeaderMsg.setIntroduction(reqPlaceLeaderMsg.getIntroduce());
        return placeLeaderMsgMapper.updateByExampleSelective(placeLeaderMsg, placeLeaderMsgExample) > 0 ? APIResponse.returnSuccess() : APIResponse.returnFail("跟新失败");
    }

    /**
     * 获取馆长信息
     * @param placeId
     * @return
     */
    @Override
    public APIResponse<RespPlaceLeaderMsg> getPlaceLeaderMsg(Integer placeId) {
        if (null == placeId) {
            return APIResponse.returnFail("场馆编号不能为空");
        }
        TbBizPlaceLeaderMsgExample placeLeaderMsgExample = new TbBizPlaceLeaderMsgExample();
        placeLeaderMsgExample.createCriteria().andPlaceIdEqualTo(placeId);
        List<TbBizPlaceLeaderMsg> placeLeaderMsgs = placeLeaderMsgMapper.selectByExample(placeLeaderMsgExample);
        if (CollectionUtils.isEmpty(placeLeaderMsgs)) {
            return APIResponse.returnFail("该馆长信息不存在");
        }
        TbBizPlaceLeaderMsg placeLeaderMsg = placeLeaderMsgs.get(0);
        RespPlaceLeaderMsg respPlaceLeaderMsg = new RespPlaceLeaderMsg();
        respPlaceLeaderMsg.setPlaceId(placeLeaderMsg.getPlaceId());
        respPlaceLeaderMsg.setUrl(placeLeaderMsg.getIconUrl());
        respPlaceLeaderMsg.setNickName(placeLeaderMsg.getNickName());
        respPlaceLeaderMsg.setMotto(placeLeaderMsg.getMotto());
        respPlaceLeaderMsg.setIntroduce(placeLeaderMsg.getIntroduction());
        return APIResponse.returnSuccess(respPlaceLeaderMsg);
    }


    private EnumCheckLength checkLeaderMsg(ReqPlaceLeaderMsg reqPlaceLeaderMsg) {
        if (checkPropertyLength(reqPlaceLeaderMsg.getNickName(), EnumCheckLength.CHECK_NICK_LENGTH.getMsg())) {
            return EnumCheckLength.CHECK_NICK_LENGTH;
        }
        if (checkPropertyLength(reqPlaceLeaderMsg.getMotto(), EnumCheckLength.CHECK_MOTTO_LENGTH.getMsg())) {
            return EnumCheckLength.CHECK_MOTTO_LENGTH;
        }
        if (checkPropertyLength(reqPlaceLeaderMsg.getIntroduce(), EnumCheckLength.CHECK_INTRO_LENGTH.getMsg())) {
            return EnumCheckLength.CHECK_INTRO_LENGTH;
        }
        return EnumCheckLength.CHECK_SUCC_LENGTH;
    }

    /**
     * 检查字段长度
     * @param property
     * @param maxLength
     * @return
     */
    private boolean checkPropertyLength(String property, int maxLength) {
        return property.length() >
                maxLength;
    }
    private enum  EnumCheckLength{
        CHECK_NICK_LENGTH(5) {
            @Override
            public String getValue() {
                return "昵称过长";
            }
        },
        CHECK_MOTTO_LENGTH(30) {
            @Override
            public String getValue() {
                return "座右铭过长";
            }
        },
        CHECK_INTRO_LENGTH(200) {
            @Override
            public String getValue() {
                return "馆长介绍过长";
            }
        },
        CHECK_SUCC_LENGTH(300) {
            @Override
            public String getValue() {
                return "成功";
            }
        };
        private Integer msg;
        EnumCheckLength(Integer msg){
            this.msg=msg;
        }
        public Integer getMsg() {
            return msg;
        }
        public abstract String getValue();
    }
}
